<template>
    <div class="popover" ref="popover">
        <div ref="contentWrapper" v-if="visiable"  class="content-wrapper" :class="contentClass">
            <slot name="content" :close="close"></slot>
        </div>
        <div ref="toggleWrapper">
            <slot></slot>
        </div>
    </div>
</template>

<script lang="ts">
  import Vue from "vue";
  import {Component, Ref, Prop} from "vue-property-decorator";

  @Component
  export default class Popover extends Vue {
    @Ref("contentWrapper") contentWrapper;
    @Ref("toggleWrapper") toggleWrapper;
    @Ref("popover") popover;
    @Prop({
      type: String,
      default: "top",
      validator(value): boolean {return ["left", "right", "top", "bottom"].indexOf(value) >= 0;}
    }) position: string;
    @Prop({
      type: String, default: "click", validator(value): boolean {
        return ["click", "hover"].indexOf(value) >= 0;
      }
    }) trigger: string;
    visiable: boolean = false;

    mounted() {
      if (this.trigger === "click") this.popover.addEventListener("click", this.toggle);
      if (this.trigger === "hover") {
        this.popover.addEventListener("mouseenter", this.open);
        this.popover.addEventListener("mouseleave", this.close)
      }
    }
    beforeDestroy() {
      if (this.trigger === "click") this.popover.removeEventListener("click", this.toggle);
      if (this.trigger === "hover") {
        this.popover.removeEventListener("mouseenter", this.open);
        this.popover.removeEventListener("mouseleave", this.close)
      }
    }

    get contentClass() {
      return {[`content-${this.position}`]: this.position};
    }

    eventsHandler(e) {
      if (this.popover?.contains(e.target) || this.contentWrapper.contains(e.target)) {
        return;
      }
      this.close();
    };

    close() {
      this.visiable = false;
      document.removeEventListener("click", this.eventsHandler);
    }

    contentPosition() {
      this.$nextTick(() => {
        document.body.appendChild(this.contentWrapper);
        const {left, top, height, width} = this.toggleWrapper.getBoundingClientRect();
        const {height: height2} = this.contentWrapper.getBoundingClientRect();
        const positions = {
          top: {
            left: left + window.scrollX + "px",
            top: top + window.scrollY + "px"
          },
          bottom: {
            left: left + window.scrollX + "px",
            top: top + height + window.scrollY + "px"
          },
          right: {
            left: left + width + window.scrollX + "px",
            top: top + (height - height2) / 2 + window.scrollY + "px"
          },
          left: {
            left: left + window.scrollX + "px",
            top: top + window.scrollY + (height - height2) / 2 + "px"
          }
        };
        this.contentWrapper.style.left = positions[this.position].left;
        this.contentWrapper.style.top = positions[this.position].top;
      });
    }

    open() {
      this.visiable = true;
      this.contentPosition();

    }

    toggle() {
      if (this.visiable) {
        this.close();
      } else {
        this.open();
        document.addEventListener("click", this.eventsHandler);
      }


    }
  }
</script>

<style lang="scss" scoped>
    %triangle {
        &::before, &::after {
            content: '';
            position: absolute;
            border: 10px solid transparent;
        }
    }

    .popover {
        display: inline-block;
        position: relative;
        vertical-align: top;
    }

    .content-wrapper {

        position: absolute;
        border: 1px solid #666666;
        /*box-shadow: 0 0 2px rgba(0, 0, 0, 0.3);*/
        filter: drop-shadow(0 0 1px rgba(0, 0, 0, 0.3));
        background: white;
        border-radius: 4px;
        padding: 0.5em 1em;
        max-width: 20em;
        word-break: break-all;
        z-index: 999;

        &.content-top {
            margin-top: -10px;
            transform: translateY(-100%);
            @extend %triangle;

            &::before {
                border-top-color: #666;
                top: 100%;
                border-bottom: none;
            }

            &::after {
                border-top-color: white;
                top: calc(100% - 1px);
                border-bottom: none;
            }
        }

        &.content-bottom {
            margin-top: 10px;
            @extend %triangle;

            &::before {
                border-bottom-color: #666;
                bottom: 100%;
                border-top: none;

            }

            &::after {
                border-bottom-color: white;
                bottom: calc(100% - 1px);
                border-top: none;

            }
        }

        &.content-left {
            margin-left: -10px;
            transform: translateX(-100%);
            @extend %triangle;

            &::before {
                border-left-color: #666;
                left: 100%;
                top: 50%;
                transform: translateY(-50%);
                border-right: none;

            }

            &::after {
                border-left-color: white;
                left: calc(100% - 1px);
                top: 50%;
                transform: translateY(-50%);
                border-right: none;

            }
        }

        &.content-right {
            margin-left: 10px;
            @extend %triangle;

            &::before {
                border-right-color: #666;
                right: 100%;
                top: 50%;
                transform: translateY(-50%);
                border-left: none;

            }

            &::after {
                border-right-color: white;
                right: calc(100% - 1px);
                top: 50%;
                transform: translateY(-50%);
                border-left: none;
            }
        }
    }
</style>